﻿#include "RenderContext.h"

#include "Framework/Application.h"

#include "VulkanContext.h"

#include "Render/Widget/RenderSurface.h"
#include "Render/PreRender/PreRenderResult.h"
#include "Render/PreRender/PreRenderWindow.h"
#include "Render/Widget/RenderWidgets.h"
#include "Render/PreRenderContext.h"

#include "Time/CPUTimeCounter.h"

static RRenderContext* Context=nullptr;
static std::atomic<bool> bRunning=false;

void RRenderContext::Initialize()
{
    Context=this;

    //启动预处理线程
    bRunning=true;
    PreProcessThread=new std::thread(&RRenderContext::PreProcessThreadRun,this);

    CVulkanContext::Get()->Initialize();
}

void RRenderContext::Deinitialize()
{
    Context=nullptr;

    //关闭预处理线程
    bRunning=false;
}

RRenderContext *RRenderContext::Get()
{
    assert(Context!=nullptr);
    return Context;
}

void RRenderContext::WriteSurfaces(const TVector<std::shared_ptr<CRenderSurface>> &InSurfaces)
{
    Surfaces[CurrentWriteBufferIndex]=InSurfaces;    
}

TVector<std::shared_ptr<CRenderSurface>> RRenderContext::ReadSurfaces()
{
    return Surfaces[CurrentReadBufferIndex];
}

void RRenderContext::PreProcessThreadRun()
{
    while(bRunning)
    {
        while(PreProcessResult.load())
        {

            if(!bRunning)
            {
                return;
            }
            
            //上一次的预处理结果还没有被使用，让出线程
            std::this_thread::yield();
        }

        while(!OccupyReadableBuffer() )
        {
            if(!bRunning)
            {
                return;
            }
            
            //没有可读的缓冲区，让出线程
            std::this_thread::yield();

        }

        BEGIN_FRAME_TIME_COUNT(PreRenderThread);

        //预处理数据
        PreRender(Surfaces[CurrentReadBufferIndex]);   

        END_FRAME_TIME_COUNT(PreRenderThread);

        //通知主线程可以写入数据
        ReleaseOccupiedReadingBuffer();

        //计算帧率
        auto Now=std::chrono::high_resolution_clock::now();
        auto Duration=Now-LastRenderTime;
        LastRenderTime=Now;
        RenderFramePerSecond=1.0f/std::chrono::duration_cast<std::chrono::duration<float>>(Duration).count();

        //等待下一帧
        auto _FrameLimit=FrameLimit.load();
        if(_FrameLimit>0)
        {
            float TargetFrameTime=1.0f/FrameLimit; //unit: second
            uint32_t TargetFrameTimeMicroS=TargetFrameTime*1000000;
            //计算上一帧到当前帧的时间间隔，单位为微秒
            auto ElapsedTimeMicroS = 
                std::chrono::duration_cast<std::chrono::microseconds>(
                    Now - LastRenderTime).count();
        
            //由于睡眠时间不精确，所以循环等待直到时间到达
            while(ElapsedTimeMicroS<=TargetFrameTimeMicroS)
            {
                std::this_thread::yield();
                Now = std::chrono::high_resolution_clock::now();
                ElapsedTimeMicroS=std::chrono::duration_cast<std::chrono::microseconds>(Now -LastRenderTime).count();
            }
            
        }
    }
}

void RRenderContext::PreRender(const TVector<std::shared_ptr<CRenderSurface>> &InSurfaces)
{
    SPreRenderContext PreRenderContext;
    PreRenderContext.Result=new CAllPreRenderData();
    PreRenderContext.Result->Windows.Reserve(InSurfaces.Num());

    for(auto& RenderWindow: InSurfaces)
    {
        
        auto PreRenderWindow=std::make_shared<CPreRenderWindow>();
        PreRenderContext.Result->Windows.Add(PreRenderWindow);

        PreRenderWindow->SystemWindow=RenderWindow->SystemWindow;
        
        // RenderWindow->MakeSureVulkanWindow();
        // PreRenderWindow->VulkanWindow=RenderWindow->VulkanWindow;
        
        for(auto& Widget:RenderWindow->Widgets[CurrentReadBufferIndex])
        {
            Widget->GeneratePreRenderWidgets(PreRenderContext,RenderWindow.get(),PreRenderWindow->AllVulkanWidgets);
        }
    }

    //通知渲染线程可以读取预处理结果
    PreProcessResult=PreRenderContext.Result;

 
}
